package com.lbi.utilities
{
	public class ArrayUtil
	{
		public function ArrayUtil()
		{
		}
		
		/**
		*	Determines whether the specified array contains the specified value.	
		* 
		* 	@param arr The array that will be checked for the specified value.
		*	@param  source the array for the opration
		*	@param value The object which will be searched for within the array
		* 	@return True if the array contains the value, False if it does not.
		*
		*/			
		public static function arrayContainsValue(arr:Array, value:Object):Boolean
		{
			return (arr.indexOf(value) != -1);
		}	
		
		/**
	     *  Add the specified item to the end of the list.
	     *  Equivalent to addItemAt(item, length);
	     * 	@param  source the array for the opration
	     *  @param item the item to add
	     */
		public static function addItem(source:Array,item:Object):void {
	        ArrayUtil.addItemAt(source,item, source.length);
	    }
	    
	    /**
	     *  Add the item at the specified index.  
	     *  Any item that was after this index is moved out by one.  
	     * 
	     *  @param  source the array for the opration
	     *  @param item the item to place at the index
	     *  @param index the index at which to place the item
	     *  @throws RangeError if index is less than 0 or greater than the length
	     */
	    public static function addItemAt(source:Array,item:Object, index:int):void {
	        if (index < 0 || index > source.length) 
			{
				var message:String = "index out of bound";
	        	throw new RangeError(message);
			}
	        	
	        source.splice(index, 0, item);
	
	    }
	    
	    /**
	     *  Return the index of the item if it is in the list such that
	     *  getItemAt(index) == item.  
	     *  Note that in this implementation the search is linear and is therefore 
	     *  O(n).
	     * 
	     *  @param  source the array for the opration
	     *  @param item the item to find
	     *  @return the index of the item, -1 if the item is not in the list.
	     */
	    public static function getItemIndex(source:Array,item:Object ):int
	    {
	        var n:int = source.length;
	        for (var i:int = 0; i < n; i++)
	        {
	            if (source[i] === item)
	                return i;
	        }
	
	        return -1;           
	    }
	    
	    /**
	     *  Get the item at the specified index.
	     * 
	     *  @param  source the array for the opration
	     *  @param 	index the index in the list from which to retrieve the item
	     *  @param	prefetch int indicating both the direction and amount of items
	     *			to fetch during the request should the item not be local.
	     *  @return the item at that index, null if there is none
	     *  @throws ItemPendingError if the data for that index needs to be 
	     *                           loaded from a remote location
	     *  @throws RangeError if the index < 0 or index >= length
	     */
	    public static function getItemAt(source:Array,index:int):Object {
	        if (index < 0 || index >= source.length)
			{
				var message:String = "index out of bound";
	        	throw new RangeError(message);
			}
	            
	        return source[index];
	    }
	    
	     /**
	     *  Removes the specified item from this list, should it exist.
	     *
	     *  @param  source the array for the opration
	     *	@param	item Object reference to the item that should be removed.
	     *  @return	Boolean indicating if the item was removed.
	     */
	    public static function removeItem(source:Array,item:Object):Boolean {
	    	var index:int = ArrayUtil.getItemIndex(source,item);
	    	var result:Boolean = index >= 0;
	    	if (result)
	    		ArrayUtil.removeItemAt(source,index);
	
	    	return result;
	    }
    
   		/**
	     *  Remove the item at the specified index and return it.  
	     *  Any items that were after this index are now one index earlier.
	     *
	     *  @param  source the array for the opration
	     *  @param index the index from which to remove the item
	     *  @return the item that was removed
	     *  @throws RangeError is index < 0 or index >= length
	     */
    	public static function removeItemAt(source:Array,index:int):Object {
	        if (index < 0 || index >= length)
			{
				var message:String = "index out of bound";
	        	throw new RangeError(message);
			}
	
	        var removed:Object = source.splice(index, 1)[0];
	        return removed;
	    }
	    
	     /** 
	     *  Remove all items from the list.
	     * 
	     *  @param  source the array for the opration
	     */
	    public static function removeAll(source:Array):void
	    {
	        if (source.length > 0)
	        {
	            source.splice(0, source.length);
	        }    
	    }
	    
	    /**
		*	Creates a copy of the specified array.
		*
		*	Note that the array returned is a new array but the items within the
		*	array are not copies of the items in the original array (but rather 
		*	references to the same items)
		* 
		*   @param  source the array for the opration
		* 	@param arr The array that will be copies
		*	@return A new array which contains the same items as the array passed
		*	in.
		*
		*/			
		
	    public static function copyArray(arr:Array):Array
		{	
			return arr.slice();
		}
		
		/**
		*	Compares two arrays and returns a boolean indicating whether the arrays
		*	contain the same values at the same indexes.
		*   
		* 	@param  source the array for the opration
		* 	@param arr1 The first array that will be compared to the second.
		* 	@param arr2 The second array that will be compared to the first.
		*
		*	@return True if the arrays contains the same values at the same indexes.
			False if they do not.
		*
		*/		
		
		public static function compareArrays(arr1:Array, arr2:Array):Boolean
		{
			if(arr1.length != arr2.length)
			{
				return false;
			}
			
			var len:Number = arr1.length;
			
			for(var i:Number = 0; i < len; i++)
			{
				if(arr1[i] !== arr2[i])
				{
					return false;
				}
			}
			
			return true;
		}
		
		/**
		*	Create a new array that only contains unique instances of objects
		*	in the specified array.
		*
		*	Basically, this can be used to remove duplication object instances
		*	from an array
		* 
		*   @param  source the array for the opration
		* 	@param arr The array which contains the values that will be used to
		*	create the new array that contains no duplicate values.
		*
		*	@return A new array which only contains unique items from the specified
		*	array.
		*
		*/	
		public static function createUniqueCopy(a:Array):Array
		{
			var newArray:Array = new Array();
			
			var len:Number = a.length;
			var item:Object;
			
			for (var i:uint = 0; i < len; ++i)
			{
				item = a[i];
				
				if(!ArrayUtil.arrayContainsValue(newArray, item))
				{
					newArray.push(item);
					
				}
				
				
			}
			trace("newArray "+newArray);
			return newArray;
		}
		
		
		 /**
	     *  Place the item at the specified index.  
	     *  If an item was already at that index the new item will replace it and it 
	     *  will be returned.
	     *	@param  source the array for the opration
	     *  @param 	item the new value for the index
	     *  @param 	index the index at which to place the item
	     *  @return the item that was replaced, null if none
	     *  @throws RangeError if index is less than 0 or greater than or equal to length
	     */
		public static function setItemAt(source:Array,item:Object, index:int):Object
	    {
	        if (index < 0 || index >= source.length) 
			{
				var message:String = "index out of bound";
	        	throw new RangeError(message);
			}
	        
	        var oldItem:Object = source[index];
	        source[index] = item;
	        
	       
	        return oldItem;    
	    }
	    
	    /**
		* Randomized the value in the Array and returns the randomized array
		* 
		* @param source  This parameter is the array which is randomized.
		* @return the randomized array 	
		*/
		public static function shuffle(source:Array):Array {
			var shuffleArray:Array = new Array();
			var tmpArray:Array = new Array();
			var length:int=source.length;
			
			while (source.length>0) {
				tmpArray.push(source.splice( Math.round((source.length-1)*Math.random()),1));
				
				//tmpArray.push(source.splice(Math.round((source.length-1)*Math.random()),1)[0]);
				
			}
			for (var i:int = 0; i<length; i++) {
				shuffleArray.push(tmpArray[i]);
			}
			
			//source = shuffleArray;
			return shuffleArray;
		}
		
		public static function concateArrays(firstArray:Array, secondArray:Array):Array {
			var concatedArray:Array = new Array();
			var arrLength:int;
				arrLength = firstArray.length;
			var i:int;
				
			if(arrLength>0){	
				for (i = 0; i<arrLength; i++) {
					concatedArray.push(firstArray[i]);
				} 
			}
			
			arrLength = secondArray.length;
			if(arrLength>0){	
				for ( i = 0; i<arrLength; i++) {
					concatedArray.push(secondArray[i]);
				} 
			}
			
				
			return concatedArray;
		}

	}
}